home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
HENSA
/
MISC
/
SHELL.ARC
/
Shell
/
Sources
/
c
/
Save102
< prev
next >
Wrap
Text File
|
1994-11-04
|
17KB
|
504 lines
/*
#### # # # #
# # # # # The FreeWare C library for
# # ## ### # # # # ### RISC OS machines
# # # # # # # # # # # ___________________________________
# # #### ### ## # # # #
# # # # # # # # # # Please refer to the accompanying
#### ### #### # # ##### # ### documentation for conditions of use
________________________________________________________________________
File: Save.Save.c
Author: Copyright © 1994 Julian Smith and Jason Howat
Version: 1.02 (18 Jun 1994)
Purpose: Automated handling of save-as window
Mods: 13-Jun-1994 - JPS - Added support for filetypes
18-Jun-1994 - JDH - Changed sense of value returned by
save_filesaver to be in line with rest of DeskLib.
save_filsaver uses filename instead of stream. Tidied code
to use core routines and proper DeskLib conventions. Added
Save__KeyHandler to check for RETURN key in text icon. For
a RETURN key or OK click, added check that filename isn't
just a leafname. Changed Save__DragIconClickHandler to use
Icon_StartSolidDrag. Changed several routines to make
messages in their own blocks -- they used to corrupt
event_lastevent. In Save__MessageHandler the initial
reference check excludes unacknowledged messages that were
returned.
04 Nov 1994 Modified to work as a Shell sublibrary - JPS.
This is because DeskLib hasn't been released with Save 1.02 yet, but
Shell requires Save 1.02.
*/
#include "DeskLib:Event.h"
#include "DeskLib:WimpSWIs.h"
#include "DeskLib:Icon.h"
#include "DeskLib:Keycodes.h"
#include "DeskLib:Error.h"
#include "DeskLib:Str.h"
#include "Desklib:File.h"
#include "Shell.Save102.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Shell_Save102_SetFiletype(Shell_Save102_saveblock *saveblock, int filetype)
{
saveblock->filetype = filetype;
Icon_FileIcon(saveblock->window, saveblock->dragsprite, filetype);
}
static void Shell_Save102__CleanIconText(window_handle window, icon_handle icon)
/* used to clean up writable-icon text - these seem to be
* terminated by '\n', which is no use to <string.h> functions.
*/
{
icon_block iconblock;
Wimp_GetIconState(window, icon, &iconblock);
Str_MakeASCIIZ(iconblock.data.indirecttext.buffer,
iconblock.data.indirecttext.bufflen-1);
}
static void Shell_Save102__ResetSaveBlock(Shell_Save102_saveblock *saveblock)
{
saveblock->ram_progress = 0;
saveblock->last_message_ref = -1;
saveblock->flags.data.we_are_dragging = FALSE;
}
static BOOL Shell_Save102__SaveDataToFilename(char *filename, Shell_Save102_saveblock *saveblock)
{
BOOL Shell_Save102_ok;
Shell_Save102_ok = saveblock->filesaver(filename, saveblock->ref);
if(Shell_Save102_ok)
File_SetType(filename, saveblock->filetype);
else
saveblock->resulthandler(Shell_Save102_FILESAVERFAILED, saveblock);
return Shell_Save102_ok;
}
static void Shell_Save102__CloseMenuOrSaveWindow(Shell_Save102_saveblock *saveblock)
/* A save has been completed with 'Select'.
* If we were part of a menu, close menu.
* If we were a save window, close this window.
* If none of the above, our window contains other things, (it might be the
* main document window with a 'Quick save' icon), so do nothing.
* The Event_ handlers will be released by Save_CloseHandler and
* Save_MenusDeletedHandler, so we don't release them here.
*/
{
if(saveblock->flags.data.is_menu)
Wimp_CreateMenu((menu_block *)-1, 0, 0); /* close menu */
if(saveblock->flags.data.is_save_window)
Wimp_CloseWindow(saveblock->window); /* close window */
}
static BOOL Shell_Save102__OKIconHandler(event_pollblock *event, void *ref)
{
icon_block iconblock;
Shell_Save102_saveblock *saveblock = (Shell_Save102_saveblock *)ref;
char *filename;
Wimp_GetIconState(saveblock->window, saveblock->filenameicon, &iconblock);
filename = iconblock.data.indirecttext.buffer;
if(LeafName(filename) != filename) /* not just a leafname in icon */
{
Shell_Save102__SaveDataToFilename(iconblock.data.indirecttext.buffer, saveblock);
Shell_Save102__ResetSaveBlock(saveblock);
if((event->type == event_CLICK && event->data.mouse.button.data.select) ||
event->type == event_KEY)
Shell_Save102__CloseMenuOrSaveWindow(saveblock);
}
else
Error_Report(0, "To save, drag the icon to a directory display");
return TRUE;
}
static BOOL Shell_Save102__KeyHandler(event_pollblock *event, void *ref)
{
if(event->data.key.code == keycode_RETURN)
return Shell_Save102__OKIconHandler(event, ref);
return FALSE;
}
static BOOL Shell_Save102__CancelIconHandler(event_pollblock *event, void *ref)
{
UNUSED_ARG(event);
Shell_Save102__CloseMenuOrSaveWindow((Shell_Save102_saveblock *)ref);
return TRUE;
}
static BOOL Shell_Save102__DragIconClickHandler(event_pollblock *event, void *ref)
{
Shell_Save102_saveblock *saveblock = (Shell_Save102_saveblock *)ref;
if(!event->data.mouse.button.data.dragselect &&
!event->data.mouse.button.data.dragadjust)
return FALSE;
saveblock->flags.data.quit_after_save =
event->data.mouse.button.data.dragselect;
saveblock->flags.data.we_are_dragging = TRUE;
Icon_StartSolidDrag(saveblock->window, saveblock->dragsprite);
return TRUE;
}
static BOOL Shell_Save102__UserDragHandler(event_pollblock *event, void *ref)
{
Shell_Save102_saveblock *saveblock = (Shell_Save102_saveblock *)ref;
mouse_block ptr;
message_block msg;
UNUSED_ARG(event);
/* Is the drag nothing to do with the save drag-icon? */
if(!saveblock->flags.data.we_are_dragging)
return FALSE;
saveblock->flags.data.we_are_dragging = FALSE;
Wimp_GetPointerInfo(&ptr);
msg.header.size = 80;
msg.header.yourref = 0;
msg.header.action = message_DATASAVE;
msg.data.datasave.window = ptr.window;
msg.data.datasave.icon = ptr.icon;
msg.data.datasave.pos = ptr.pos;
msg.data.datasave.estsize = saveblock->estimatedsize;
msg.data.datasave.filetype = saveblock->filetype;
strcpy(msg.data.datasave.leafname,
LeafName(Icon_GetTextPtr(saveblock->window, saveblock->filenameicon)));
Wimp_SendMessage(event_SENDWANTACK, &msg, ptr.window, ptr.icon);
saveblock->last_message_ref = msg.header.myref;
return TRUE;
}
static BOOL Shell_Save102__MenusDeletedOrWindowClosedHandler(event_pollblock *event,
void *ref)
{
Shell_Save102_saveblock *saveblock = (Shell_Save102_saveblock *)ref;
/* Don't release handlers when menu/window is closed */
if(!saveblock->flags.data.release_after)
return FALSE;
if((event->type == event_SEND && saveblock->flags.data.is_menu &&
event->data.message.header.action == message_MENUSDELETED) ||
(event->type == event_CLOSE && saveblock->flags.data.is_save_window))
{
Shell_Save102_ReleaseSaveHandlers(ref);
free(saveblock);
}
return FALSE;
}
static BOOL Shell_Save102__MessageHandler(event_pollblock *event, void *ref)
{
Shell_Save102_saveblock *saveblock = (Shell_Save102_saveblock *)ref;
message_block *msg = &event->data.message;
if(event->type != event_ACK &&
msg->header.yourref != saveblock->last_message_ref)
return FALSE;
/* we are only interested in replies to our previous messages...
or unacknowledged messages */
if(msg->header.action == message_DATASAVE)
{
/* User has dragged onto useless part of the desktop...
* This could be our original message_SENDWANTACK being sent to us
* because the sprite was dragged onto one of *our task's* windows,
* or a message_ACK sent to us by the WIMP because nobody responded
* to our original message.
*/
return FALSE; /* the app might want to deal with this
* message to save into itself.
*/
}
if(msg->header.action == message_DATASAVEACK)
{
BOOL save_ok;
save_ok = Shell_Save102__SaveDataToFilename(msg->data.datasaveack.filename,
saveblock);
if(save_ok)
{
message_block reply;
memcpy(&reply, msg, sizeof(message_block));
reply.header.action = message_DATALOAD;
reply.data.dataload.size = 49;
reply.header.yourref = reply.header.myref;
Wimp_SendMessage(event_SENDWANTACK, &reply, reply.header.sender, 0);
saveblock->last_message_ref = reply.header.myref;
}
else
Shell_Save102__ResetSaveBlock(saveblock);
return TRUE;
}
if(msg->header.action == message_RAMFETCH)
{
/* If we ignore message_RAMFETCH, the receiving task should
* try again using a transfer through <Wimp$Scrap>.
*/
int byteswritten;
BOOL last_ramtransfer;
message_block reply;
if(saveblock->ramsaver == NULL)
return TRUE;
byteswritten = (saveblock->ramsaver)(event_taskhandle, saveblock->ref,
msg->header.sender,
msg->data.ramfetch.buffer,
msg->data.ramfetch.buffsize,
saveblock->ram_progress);
last_ramtransfer = byteswritten < msg->data.ramfetch.buffsize;
saveblock->ram_progress += byteswritten;
if(byteswritten < 0)
{
(saveblock->resulthandler)(Shell_Save102_RAMSAVERFAILED, saveblock);
Shell_Save102__ResetSaveBlock(saveblock);
return TRUE;
}
memcpy(&reply, msg, sizeof(message_block));
reply.header.yourref = reply.header.myref;
reply.header.action = message_RAMTRANSMIT;
reply.data.ramtransmit.byteswritten = byteswritten;
Wimp_SendMessage((last_ramtransfer) ? event_SEND : event_SENDWANTACK,
&reply, reply.header.sender, 0);
saveblock->last_message_ref = reply.header.myref;
if(last_ramtransfer)
{
Shell_Save102__ResetSaveBlock(saveblock);
if(saveblock->flags.data.quit_after_save)
Shell_Save102__CloseMenuOrSaveWindow(saveblock);
(saveblock->resulthandler)(Shell_Save102_SAVEOK, saveblock->ref);
}
return TRUE;
}
if(msg->header.action == message_RAMTRANSMIT)
{
/* This is our message being returned to us by the Wimp */
Shell_Save102__ResetSaveBlock(saveblock);
(saveblock->resulthandler)(Shell_Save102_RECEIVERFAILED, saveblock->ref);
return TRUE;
}
if(msg->header.action == message_DATALOADACK)
{
/* everything OK */
Shell_Save102__ResetSaveBlock(saveblock);
if(saveblock->flags.data.quit_after_save)
Shell_Save102__CloseMenuOrSaveWindow(saveblock);
(saveblock->resulthandler)(Shell_Save102_SAVEOK, saveblock->ref);
return TRUE;
}
if(msg->header.action == message_DATALOAD)
{
/* This is our message being returned to us by the Wimp */
Error_Report(0, "Received DATALOAD back - scrap file not loaded...");
Shell_Save102__ResetSaveBlock(saveblock);
(saveblock->resulthandler)(Shell_Save102_RECEIVERFAILED, saveblock->ref);
return TRUE;
}
return FALSE;
}
static void Shell_Save102__DefaultResultHandler(Shell_Save102_result result, void *ref)
{
UNUSED_ARG(ref);
switch(result)
{
case Shell_Save102_RECEIVERFAILED:
Error_Report(0, "Receiver failed to load scrap file");
break;
case Shell_Save102_FILESAVERFAILED:
Error_Report(0, "Filer-saver failed");
break;
case Shell_Save102_RAMSAVERFAILED:
Error_Report(0, "RAM-saver failed");
break;
}
}
typedef BOOL (*Shell_Save102_eventclaimorreleasefn)(event_type eventtype,
window_handle window,
icon_handle icon,
event_handler handler,
void *reference);
/* This just defines a function pointer which can point
* to the two functions Event_Claim and Event_Release.
*/
static void Shell_Save102__EventClaimOrRelease(Shell_Save102_saveblock *saveblock,
Shell_Save102_eventclaimorreleasefn fn)
{
if(saveblock->dragsprite >= 0)
{
(fn)(event_CLICK, saveblock->window, saveblock->dragsprite,
Shell_Save102__DragIconClickHandler, saveblock);
(fn)(event_USERDRAG, event_ANY, event_ANY,
Shell_Save102__UserDragHandler, saveblock);
}
if(saveblock->okbutton >= 0)
(fn)(event_CLICK, saveblock->window, saveblock->okbutton,
Shell_Save102__OKIconHandler, saveblock);
if(saveblock->cancelbutton >= 0)
(fn)(event_CLICK, saveblock->window, saveblock->cancelbutton,
Shell_Save102__CancelIconHandler, saveblock);
(fn)(event_KEY, saveblock->window, saveblock->filenameicon,
Shell_Save102__KeyHandler, saveblock);
(fn)(event_CLOSE, saveblock->window, event_ANY,
Shell_Save102__MenusDeletedOrWindowClosedHandler, saveblock);
(fn)(event_SEND, event_ANY, event_ANY,
Shell_Save102__MenusDeletedOrWindowClosedHandler, saveblock);
/* we always want to check whether to release the handlers
* when a menu has been closed because flags.data.is_menu
* may be changed after Save_InitSaveWindowHandler
*/
(fn)(event_SEND, event_ANY, event_ANY, Shell_Save102__MessageHandler, saveblock);
(fn)(event_SENDWANTACK, event_ANY, event_ANY,
Shell_Save102__MessageHandler, saveblock);
(fn)(event_ACK, event_ANY, event_ANY, Shell_Save102__MessageHandler, saveblock);
}
Shell_Save102_saveblock *Shell_Save102_InitSaveWindowHandler(window_handle window,
BOOL is_menu,
BOOL is_save_window,
BOOL release_after,
icon_handle dragsprite,
icon_handle okbutton,
icon_handle cancelbutton,
icon_handle filenameicon,
Shell_Save102_filesaver filesaver,
Shell_Save102_ramsaver ramsaver,
Shell_Save102_resulthandler resulthandler,
size_t estimatedsize,
int filetype,
void *ref)
{
Shell_Save102_saveblock *saveblock;
if(!filesaver)
{
/* Must have a file-saver */
Error_Report(0, "Shell_Save102_InitSaveWindowHandler called with NULL filesaver");
return NULL;
}
saveblock = malloc(sizeof(Shell_Save102_saveblock));
if(!saveblock)
{
Error_OutOfMemory(FALSE, "save window");
return NULL;
}
saveblock->window = window;
saveblock->flags.data.is_menu = is_menu;
saveblock->flags.data.is_save_window = is_save_window;
saveblock->flags.data.release_after = release_after;
saveblock->dragsprite = dragsprite;
saveblock->okbutton = okbutton;
saveblock->cancelbutton = cancelbutton;
saveblock->filenameicon = filenameicon;
saveblock->filesaver = filesaver;
saveblock->ramsaver = ramsaver;
saveblock->resulthandler = resulthandler;
saveblock->estimatedsize = estimatedsize;
saveblock->ref = ref;
Shell_Save102_SetFiletype(saveblock, filetype);
Shell_Save102__ResetSaveBlock(saveblock);
if(saveblock->resulthandler == NULL)
saveblock->resulthandler = Shell_Save102__DefaultResultHandler;
Shell_Save102__CleanIconText(saveblock->window, saveblock->filenameicon);
/* Make sure the terminator of the filename is '\0' - templates
* seem to come with a '\n' as terminator.
*/
Shell_Save102__EventClaimOrRelease(saveblock, Event_Claim);
return saveblock;
}
void Shell_Save102_ReleaseSaveHandlers(Shell_Save102_saveblock *saveblock)
{
Shell_Save102__EventClaimOrRelease(saveblock, Event_Release);
}